# Refresh 下拉刷新

# 基础用法

import 'package:flutter/material.dart';
import 'package:millui/millui.dart';
import 'dart:math';

import '../app_provider.dart';

class Refash extends StatefulWidget {
  _Refash createState() => new _Refash();
}

class _Refash extends State<Refash> {
  List _items = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];

  Future<dynamic> _refresh() async {
    return await Future.delayed(Duration(milliseconds: 1000), () {
      if (mounted) {
        setState(() {
          _items = List.generate(10, (index) => 'item$index');
        });
      }
      return _items;
    });
  }

  Future<dynamic> _onLoad() async {
    await Future.delayed(Duration(milliseconds: 500), () {
      i++;
      List l = List.generate(10, (index) => 'item${index + i * 10}');
      _items.addAll(l);
      if (mounted) {
        setState(() {
          _items = _items;
        });
      }
    });
  }

  
  Widget build(BuildContext context) {
    bool isCn = getLanage(context);

    return Scaffold(
      appBar: AppBar(
        title: Text('refresh'),
      ),
      body: Stack(
        children: [
          Column(
            children: [
              Container(
                height: 30,
                child: Text('Top'),
              ),
              Expanded(
                flex: 1,
                child: MillRefresh(
                  timeout: 6,   //请求超时时间设置为
                  sliverList: _buildList(_items),
                  dropText: isCn ? '下拉刷新' : 'pulldown ↓',
                  releaseText: isCn ? '释放加载' : 'release ↑',
                  footReleaseText: isCn ? '释放加载' : 'release ↓',
                  noDataText: isCn ? '没有更多数据' : 'NO DATA',
                  refreshing: MillBallScaleLoading(),
                  loading: MillBallRotateLoading(size: 2, paintSize: 16,),
                  onRefresh: _refresh,
                  onLoad: _onLoad,
                ),
              ),
            ],
        ],
      ),
    );
  }
}

Widget _buildList(items) {
  return SliverList(
      delegate: SliverChildBuilderDelegate(
    (context, index) {
      return Container(
        padding: EdgeInsets.all(20),
        child: Text('${items[index]}'),
      );
    },
    childCount: items.length,
  ));
}

class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
  _SliverAppBarDelegate({
     this.minHeight,
     this.maxHeight,
     this.child,
  });

  final double minHeight;
  final double maxHeight;
  final Widget child;

  
  double get minExtent => minHeight;

  
  double get maxExtent => max(maxHeight, minHeight);

  
  Widget build(
      BuildContext context, double shrinkOffset, bool overlapsContent) {
    return new SizedBox.expand(child: child);
  }

  
  bool shouldRebuild(_SliverAppBarDelegate oldDelegate) {
    return maxHeight != oldDelegate.maxHeight ||
        minHeight != oldDelegate.minHeight ||
        child != oldDelegate.child;
  }
}

device-2020-08-10-110957.png

# 设置 Adapter

import 'package:flutter/material.dart';
import 'package:millui/millui.dart';
import 'dart:math';

class Refash extends StatefulWidget {
  _Refash createState() => new _Refash();
}

class _Refash extends State<Refash> {
  List _items = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];

  Future<dynamic> _refresh() async {
    return await Future.delayed(Duration(milliseconds: 1000), () {
      if (mounted) {
        setState(() {
          _items = List.generate(10, (index) => 'item$index');
        });
      }
      return _items;
    });
  }

  Future<dynamic> _onLoad() async {
    await Future.delayed(Duration(milliseconds: 500), () {
      i++;
      List l = List.generate(10, (index) => 'item${index + i * 10}');
      _items.addAll(l);
      if (mounted) {
        setState(() {
          _items = _items;
        });
      }
    });
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('refresh'),
      ),
      body: MillRefresh(
        cacheExtent: 1000.0,
        timeout: 6,
        sliverList: _buildList(_items),
        dropText: isCn ? '下拉刷新' : 'pulldown ↓',
        releaseText: isCn ? '释放加载' : 'release ↑',
        footReleaseText: isCn ? '释放加载' : 'release ↓',
        noDataText: isCn ? '没有更多数据' : 'NO DATA',
        refreshing: MillBarBeatLoading(),
        loading: MillBallRotateLoading(
          size: 2,
          paintSize: 16,
        ),
        onRefresh: _refresh,
        onLoad: _onLoad,
        preAdapter: [
          SliverToBoxAdapter(
            child: Container(
              alignment: Alignment.center,
              height: 60,
              child: Text('你好, 一个可滚动组件'),
            ),
          ),
          SliverPersistentHeader(
            pinned: true, //是否固定在顶部
            floating: true,
            delegate: _SliverAppBarDelegate(
              minHeight: 60, //收起的高度
              maxHeight: 60, //展开的最大高度
              child: Container(
                height: 60,
                alignment: Alignment.center,
                child: Text(
                  isCn ? '吸顶导航' : 'fix',
                  style: TextStyle(
                    color: Colors.white,
                  ),
                ),
                color: Colors.redAccent,
              ),
            ),
          ),
        ],
      ),
    );
  }
}

Widget _buildList(items) {
  return SliverList(
      delegate: SliverChildBuilderDelegate(
    (context, index) {
      return Container(
        padding: EdgeInsets.all(20),
        child: Text('${items[index]}'),
      );
    },
    childCount: items.length,
  ));
}

class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
  _SliverAppBarDelegate({
     this.minHeight,
     this.maxHeight,
     this.child,
  });

  final double minHeight;
  final double maxHeight;
  final Widget child;

  
  double get minExtent => minHeight;

  
  double get maxExtent => max(maxHeight, minHeight);

  
  Widget build(
      BuildContext context, double shrinkOffset, bool overlapsContent) {
    return new SizedBox.expand(child: child);
  }

  
  bool shouldRebuild(_SliverAppBarDelegate oldDelegate) {
    return maxHeight != oldDelegate.maxHeight ||
        minHeight != oldDelegate.minHeight ||
        child != oldDelegate.child;
  }
}

# 初始化调用

设置 initData 可以初始化自动调用一次

MillRefresh(
  cacheExtent: 1000.0,
  timeout: 6,
  sliverList: _buildList(_items),
  dropText: isCn ? '下拉刷新' : 'pulldown ↓',
  releaseText: isCn ? '释放加载' : 'release ↑',
  footReleaseText: isCn ? '释放加载' : 'release ↓',
  noDataText: isCn ? '没有更多数据' : 'NO DATA',
  refreshing: MillBarBeatLoading(),
  loading: MillBallRotateLoading(
    size: 2,
    paintSize: 16,
  ),
  initData: _refresh,
  onRefresh: _refresh,
  onLoad: _onLoad,
)
device-2020-08-10-110957.png

# 设置滚动回调

onNotification 可以判断当前滚动状态

MillRefresh(
    cacheExtent: 1000.0,
    timeout: 6,
    sliverList: _buildList(_items),
    dropText: isCn ? '下拉刷新' : 'pulldown ↓',
    releaseText: isCn ? '释放加载' : 'release ↑',
    footReleaseText: isCn ? '释放加载' : 'release ↓',
    noDataText: isCn ? '没有更多数据' : 'NO DATA',
    refreshing: MillBarBeatLoading(),
    loading: MillBallRotateLoading(
      size: 2,
      paintSize: 16,
    ),
    initData: _refresh,
    onRefresh: _refresh,
    onLoad: _onLoad,
    onNotification: (notification) {
      if (notification is ScrollUpdateNotification) {
         print('update');
      } else if (notification is ScrollEndNotification) {
         print('end');
      }
      return true;
    },
  )

# Attributes

字段名称 说明 类型 默认值
sliverList 列表 _SliverList SliverToBoxAdapter/List_
onRefresh 刷新回调 Function
onLoad 加载回调 Function
initData 初次加载时调用的函数,设置后,会自动执行一次下拉刷新的操作,并执行此方法。 Function
refreshFinished 刷新完成的 widget Widget
refreshing 刷新中的(顶部) widget Widget
loading 加载中展示的(底部) widget Widget
initDataSuccess 初始化数据成功 widget Widget 数据已更新
initDataError 初始化数据失败的 widget Widget 数据更新失败
error 加载超时展示的 widget Widget
timeout 请求超时时间 (秒) int 10
headerBgColor 头部下拉时的颜色 Color
footerBgColor 底部刷新时的背景颜色 Color
preAdapter List
sufAdapter SliverToBoxAdapter
hasMore 是否有更多数据 bool false
dropText 顶部下拉展示的文案 String 下拉刷新
releaseText 顶部释放展示的文案 String 释放加载
footReleaseText 底部释放展示的文案 String 释放加载
noDataText 无数据展示的文案 String 没有更多数据
onNotification 列表滚动时的回调 bool Function(ScrollNotification)
cacheExtent CustomScrollView 的 cacheExtent 属性 double
controller CustomScrollView 的 controller ScrollController